package com.ld.shieldsb.common.core.encryptor;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

/**
 * MD5不可逆加密工具类<br/>
 * MD5 是一个广为流传的 Hash 算法, 但它并不安全且所生成的 Hash 值也是相当的薄弱。它主要的优点在于生成速度快且易于实现。 但是，这也意味着它是容易被暴力攻击和字典攻击。例如使用明文和 Hash 生成的彩虹表可以快速地搜索已知 Hash 对应的原数据。
 * 此外，MD5 并没有避免 Hash 碰撞：这意味不同的密码会导致生成相同的 Hash 值。 不过，如果你仍然需要使用 MD5，可以考虑为其加 salt 来进一步保证它的安全性。
 * 
 * @author ThinkGem
 */
public class Md5Encryptor {

    private static final String MD5 = "MD5";

    private Md5Encryptor() {
        throw new IllegalStateException("该类不可初始化");
    }

    /**
     * 生成随机的Byte[]作为salt密钥.
     * 
     * @Title getSalt
     * @author 吕凯
     * @date 2018年12月5日 下午2:44:13
     * @param numBytes
     * @return byte[]
     */
    public static byte[] getSalt(int numBytes) {
        return DigestUtils.getSalt(numBytes);
    }

    /**
     * 对输入字符串进行md5散列.
     * 
     * @param input
     *            加密字符串
     */
    public static String md5(String input) {
        return md5(input, 1);
    }

    /**
     * 对输入字符串进行md5散列.
     * 
     * @param input
     *            字符串
     * @param iterations
     *            迭代次数
     */
    public static String md5(String input, int iterations) {
        return EncodeUtils.encodeHex(DigestUtils.digest(input.getBytes(StandardCharsets.UTF_8), MD5, null, iterations));
    }

    /**
     * 对输入字符串进行md5散列.
     * 
     * @param input
     *            加密字符串
     */
    public static byte[] md5(byte[] input) {
        return md5(input, 1);
    }

    /**
     * 对输入字符串进行md5散列.
     * 
     * @param input
     *            加密字符串
     * @param iterations
     *            迭代次数
     */
    public static byte[] md5(byte[] input, int iterations) {
        return md5(input, null, iterations);
    }

    /**
     * 
     * 对输入字符串进行md5散列.
     * 
     * @Title md5
     * @author 吕凯
     * @date 2018年12月5日 下午2:47:45
     * @param input
     * @param salt
     * @return byte[]
     */
    public static byte[] md5(byte[] input, byte[] salt) {
        return md5(input, salt, 1);
    }

    /**
     * 
     * 对输入字符串进行md5散列.
     * 
     * @Title md5
     * @author 吕凯
     * @date 2018年12月5日 下午2:47:57
     * @param input
     * @param salt
     * @param iterations
     * @return byte[]
     */
    public static byte[] md5(byte[] input, byte[] salt, int iterations) {
        return DigestUtils.digest(input, MD5, salt, iterations);
    }

    /**
     * 对输入流进行md5散列.
     */
    public static byte[] md5(InputStream input) throws IOException {
        return DigestUtils.digest(input, MD5);
    }

    /**
     * 获取文件的MD5字符串(转换为16进制字符串)
     * 
     * @Title md5
     * @author 吕凯
     * @date 2019年1月26日 上午11:27:06
     * @param file
     * @return
     * @throws IOException
     *             String
     */
    public static String md5(File file) throws IOException {
        String result = null;
        try (InputStream fis = new FileInputStream(file)) {
            byte[] buffer = md5(fis);
            result = EncodeUtils.encodeHex(buffer);
        }
        return result;
    }

}
